﻿package net.nicoptere.utils 
{
	
	/**
	 * ...
	 * @author nicolas barradeau
	 */
	public class ArrayUtil
	{
		
		public function ArrayUtil() { }
		
		/**
		 * removes all duplicates from an array 
		 * @param	args input array
		 * @return  the modified array that only contains unique items
		 */
		static public function singleValues( args:Array ):Array
		{
			if ( args.length < 2 ) return args;
			var i:int, j:int, item:*, needle:*;
			for ( i = 0; i < args.length; i++) 
			{
				item = args[ i ];
				for ( j = ( i+1 ); j < args.length; j++) 
				{
					needle = args[ j ];
					if( item === needle )
					{
						args.splice( j , 1 );
					}
				}
			}
			return args;
		}
		
		/**
		 * shuffles the values an array
		 * @param	args input array
		 * @return the shuffled array
		 */
		static public function randomize( args:Array ):Array
		{
			
			var _length:int = args.length, mixed:Array = args.concat(), rn:int, it:int, el:*;
			for (it = 0; it < _length; it++)
			{
				el = mixed[ it ];
				mixed[ it ] = mixed[ rn = int( Math.random()*_length ) ];
				mixed[ rn ] = el;
			}
			return mixed;
			
		}
		
		
		/**
		*       Determines whether the specified array contains the specified value.
		*       @param arr The array that will be checked for the specified value.
		*       @param value The object which will be searched for within the array
		*       @return True if the array contains the value, False if it does not.
		*/                      
		public static function contains(arr:Array, value:Object ):Boolean
		{
			return (arr.indexOf(value) != -1);
		}       
		
		/**
		*       Remove all instances of the specified value from the array,
		*       @param arr The array from which the value will be removed
		*       @param value The object that will be removed from the array.
		*/              
		public static function removeValue(arr:Array, value:Object):void
		{
			var i:int, len:uint = arr.length;
			for ( i = 0; i < len; i++ )
			{
				if(arr[i] === value)
				{
					arr.splice(i, 1);
				}
			}                                       
		}
		
		/**
		*       @usage returns the index of a given value of the array
		*       @param arr The array from which the index will be got
		*       @param value The object's index we're looking for
		* 		@return int the index of the value,  first value found is return default is -1 ( no key is matching )
		*/
		public static function getKey( arr:Array, value:* ):int
		{
			var i:int, len:uint = arr.length;
			for ( i = 0; i < len; i++ )
			{
				if(arr[i] === value)
				{
					return i;
				}
			}                
			return -1;
		}
		
		/**
		*       @usage interverts two elements of the array
		*       @param arr The array from which elements will be swapped
		*       @param item0 first object to swap
		*       @param item1 second object to swap
		* 		@return new array with swapped items
		*/
		public static function swapItems( arr:Array, item0:*, item1:* ):void
		{
			var k0:int = getKey( arr, item0 );
			var k1:int = getKey( arr, item1 );
			
			if ( k0 == -1 || k1 == -1 ) return;
			
			var tmp:* = arr[ k0 ];
			arr[ k0 ] = arr[ k1 ];
			arr[ k1 ] = tmp;
			
		}
		/**
		*       @usage interverts two elements of the array after their ids in the array
		*       @param arr The array from which elements will be swapped
		*       @param id0 first id to swap
		*       @param id1 second id to swap
		* 		@return new array with swapped items
		*/
		public static function swapItemsById( arr:Array, id0:int, id1:int ):void
		{
			
			if ( id0 < 0 ) id0 = 0;
			if ( id0 > arr.length - 1 ) id0 = arr.length - 1;
			if ( id1 < 0 ) id1 = 0;
			if ( id1 > arr.length - 1 ) id1 = arr.length - 1;
			
			if ( arr[ id0 ] == null || arr[ id1 ] == null ) return;
			
			var tmp:* = arr[ id0 ];
			arr[ id0 ] = arr[ id1 ];
			arr[ id1 ] = tmp;
			
		}
		
		/**
		*      	inserts an item at a given position in the array
		*       @param arr the array to insert item into
		*       @param id the position at which the item will be inserted
		*       @param value The object that will be inserted into the array
		* 		@return the modified array
		*/              
		public static function addAt( arr:Array, id:int, value:* ):Array
		{
			if ( id >= arr.length )
			{
				arr.push( value );
			}
			else
			{
				
				var tmp:Array = arr.concat().splice( 0, id );
				tmp.push( value );
				tmp.push( arr.concat().splice( id, arr.length ) );
				arr = tmp.concat();
				
			}
			return arr;
		}

		/**
		*       Create a new array that only contains unique instances of objects in the specified array. Basically, this can be used to remove duplication object instances from an array
		*       @param arr The array which contains the values that will be used to create the new array that contains no duplicate values.
		*		@return A new array which only contains unique items from the specified array.
		*/      
		public static function clone(a:Array):Array
		{
			var newArray:Array = new Array();
			var len:Number = a.length;
			var item:Object;
			for (var i:uint = 0; i < len; ++i)
			{
				item = a[i];
				if( contains(newArray, item) )
				{
					continue;
				}
				newArray.push(item);
			}
			return newArray;
		}
		
		/**
		*       Compares two arrays and returns a boolean indicating whether the arrays contain the same values at the same indexes.
		*       @param arr1 The first array that will be compared to the second.
		*       @param arr2 The second array that will be compared to the first.
		*       @return True if the arrays contains the same values at the same indexes.
				False if they do not.
		*/              
		public static function equals(arr1:Array, arr2:Array):Boolean
		{
			if(arr1.length != arr2.length)
			{
				return false;
			}
			var len:Number = arr1.length;
			for(var i:Number = 0; i < len; i++)
			{
				if(arr1[i] !== arr2[i])
				{
					return false;
				}
			}
			return true;
		}

		
	}
	
}